package com.neusoft.databus.core.hbase;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.hadoop.hbase.HbaseTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.neusoft.bizcore.web.dto.result.PageResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.exception.CustomRuntimeException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.databus.common.constant.DatabusErrorCode;
import com.neusoft.databus.common.dto.MonitorDataDTO;
import com.neusoft.databus.core.service.MonitorDataService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 监控指标数据控制器
 *
 * @author naxiang
 */
@Api("监控指标数据控制器")
@RestController
@ConditionalOnClass(HbaseTemplate.class)
@ConditionalOnProperty(name = "databus.core.hbase.enabled", havingValue = "true")
@RequestMapping(value = {"/api/w/monitordata", "/api/w/monitordatas" })
public class MonitorDataHBaseController {

    @Autowired
    private MonitorDataService monitorDataHBaseService;

    /**
     * 分页查询监控指标数据
     *
     * @param searchable
     * @param pageable
     * @return
     */
    @ApiOperation("分页查询监控指标数据")
    @GetMapping("/p")
    public PageResultDTO<?> search(final Searchable searchable, final Pageable pageable) {
        final String resourceCode = searchable.getStrValue("resourceCode");
        if (null == resourceCode) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406111, new Object[] {"资源编码不能为空" });
        }

        final Page<MonitorDataDTO> pageData = this.monitorDataHBaseService.search(pageable, searchable);
        return PageResultDTO.success(pageData);
    }

    /**
     * 查询监控指标数据
     *
     * @param resourceCode
     * @return
     */
    @ApiOperation("查询监控指标数据")
    @GetMapping("/{resourceCode}")
    public ResultListDTO<?> search(@PathVariable String resourceCode, final Searchable searchable) {
        final List<MonitorDataDTO> dtos = this.monitorDataHBaseService.search(resourceCode, searchable);
        return ResultListDTO.success(dtos);
    }

    /**
     * 查询监控指标实时数据
     *
     * @param resourceCode
     * @return
     */
    @ApiOperation("查询监控指标实时数据")
    @GetMapping("/realtime/{resourceCode}")
    public ResultDTO<?> realtimeData(@PathVariable String resourceCode) {
        final Map<String, Object> map = this.monitorDataHBaseService.findInCache(resourceCode);
        return ResultDTO.success(map);
    }

    /**
     * 根据资源编码列表和开始截止时间查询第一条和最后一条数据
     *
     * @param searchable
     * @return
     */
    @ApiOperation("根据资源编码列表和开始截止时间查询第一条和最后一条数据")
    @GetMapping("/range")
    public ResultDTO<?> search(final Searchable searchable) {
        if (!(searchable.hasKey("resources") && searchable.hasKey("startTime") && searchable.hasKey("endTime"))) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_400002,
                    new Object[] {"查询条件应包含resourses,startTime和endTime" });
        }

        final String[] resourceCodes = searchable.getStrArray("resources");
        final long startTime = searchable.getLongValue("startTime");
        final long endTime = searchable.getLongValue("endTime");
        final Map<String, List<Map<String, Object>>> results =
                this.monitorDataHBaseService.search(Arrays.asList(resourceCodes), startTime, endTime);
        return ResultDTO.success(results);
    }

    /**
     * @param resourceCode 资源编码
     * @param day 小于等于0
     * @return
     */
    @ApiOperation("查询资源日监控数据量")
    @GetMapping("/statistics/{resourceCode}/{day}")
    @Cacheable(value = "monitorDayCount")
    public ResultDTO<?> countOfDay(@PathVariable String resourceCode, @PathVariable int day) {
        return ResultDTO.success(this.monitorDataHBaseService.countOfDay(resourceCode, day));
    }

}
